// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: content filter topic
// ------------------------------------------------------------------

#ifndef XMLPARSER_RTPSPARTICIPANTALLOCATIONATTRIBUTES_H_
#define XMLPARSER_RTPSPARTICIPANTALLOCATIONATTRIBUTES_H_

#include <deps/common/collections/ResourceLimitedContainerConfig.hpp>
#include <deps/common/collections/ResourceLimitedVector.hpp>
#include <deps/common/fixed_size_string.hpp>
#include <deps/qos/BaseQosPolicy.hpp>

namespace vbsutil {
namespace xmlparser {
/**
 * @brief Holds limits for collections of remote locators.
 */
struct RemoteLocatorsAllocationAttributes {
    bool operator==(const RemoteLocatorsAllocationAttributes& b) const {
        return (this->max_unicast_locators == b.max_unicast_locators) &&
               (this->max_multicast_locators == b.max_multicast_locators);
    }

    /** Maximum number of unicast locators per remote entity.
     *
     * This attribute controls the maximum number of unicast locators to keep for
     * each discovered remote entity (be it a participant, reader of writer). It is
     * recommended to use the highest number of local addresses found on all the systems
     * belonging to the same domain as this participant.
     */
    size_t max_unicast_locators = 4u;

    /** Maximum number of multicast locators per remote entity.
     *
     * This attribute controls the maximum number of multicast locators to keep for
     * each discovered remote entity (be it a participant, reader of writer). The
     * default value of 1 is usually enough, as it doesn't make sense to add more
     * than one multicast locator per entity.
     */
    size_t max_multicast_locators = 1u;
};

/**
 * @brief Holds limits for send buffers allocations.
 */
struct SendBuffersAllocationAttributes {
    bool operator==(const SendBuffersAllocationAttributes& b) const {
        return (this->preallocated_number == b.preallocated_number) && (this->dynamic == b.dynamic);
    }

    /** Initial number of send buffers to allocate.
     *
     * This attribute controls the initial number of send buffers to be allocated.
     * The default value of 0 will perform an initial guess of the number of buffers
     * required, based on the number of threads from which a send operation could be
     * started.
     */
    size_t preallocated_number = 0U;

    /** Whether the number of send buffers is allowed to grow.
     *
     * This attribute controls how the buffer manager behaves when a send buffer is not
     * available. When true, a new buffer will be created. When false, it will wait for a
     * buffer to be returned. This is a trade-off between latency and dynamic allocations.
     */
    bool dynamic = false;
};

/**
 * @brief Holds limits for variable-length data.
 */
struct VariableLengthDataLimits {
    bool operator==(const VariableLengthDataLimits& b) const {
        return (this->max_properties == b.max_properties) && (this->max_user_data == b.max_user_data) &&
               (this->max_partitions == b.max_partitions);
    }

    //! Defines the maximum size (in octets) of properties data in the local or remote participant
    size_t max_properties = 0U;
    //! Defines the maximum size (in octets) of user data in the local or remote participant
    size_t max_user_data = 0U;
    //! Defines the maximum size (in octets) of partitions data
    size_t max_partitions = 0U;
};
#if 0
/**
 * Information about the content filter being applied by a reader.
 * @ingroup BUILTIN_MODULE
 */
class ContentFilterProperty {
 public:
    static const uint32_t parameters_limit_ = 100;
    /// Name of the content filtered topic on which the reader was created
    string_255 content_filtered_topic_name;
    /// Name of the related topic being filtered
    string_255 related_topic_name;
    /// Class name of the filter being used.
    /// May be empty to indicate the ContentFilterProperty is not present.
    string_255 filter_class_name;
    /// Filter expression indicating which content the reader wants to receive.
    /// May be empty to indicate the ContentFilterProperty is not present.
    std::string filter_expression;
    /// List of values for the parameters present on the filter expression
    ResourceLimitedVector<string_255, std::true_type> expression_parameters{{0, parameters_limit_, 1}};
};
#endif
/**
 * @brief Holds allocation limits affecting collections managed by a participant.
 */
struct RTPSParticipantAllocationAttributes {
    //! Holds limits for collections of remote locators.
    RemoteLocatorsAllocationAttributes locators;
    //! Defines the allocation behaviour for collections dependent on the total number of
    //! participants.
    ResourceLimitedContainerConfig participants;
    //! Defines the allocation behaviour for collections dependent on the total number of readers
    //! per participant.
    ResourceLimitedContainerConfig readers;
    //! Defines the allocation behaviour for collections dependent on the total number of writers
    //! per participant.
    ResourceLimitedContainerConfig writers;
    //! Defines the allocation behaviour for the send buffer manager.
    SendBuffersAllocationAttributes send_buffers;
    //! Holds limits for variable-length data
    VariableLengthDataLimits data_limits;

    ResourceLimitedContainerConfig total_readers() const { return total_endpoints(readers); }

    ResourceLimitedContainerConfig total_writers() const { return total_endpoints(writers); }

    bool operator==(const RTPSParticipantAllocationAttributes& b) const {
        return (this->locators == b.locators) && (this->participants == b.participants) &&
               (this->readers == b.readers) && (this->writers == b.writers) && (this->send_buffers == b.send_buffers) &&
               (this->data_limits == b.data_limits);
    }

 private:
    ResourceLimitedContainerConfig total_endpoints(const ResourceLimitedContainerConfig& endpoints) const {
        constexpr size_t max = (std::numeric_limits<size_t>::max)();
        size_t initial;
        size_t maximum;
        size_t increment;

        initial = participants.initial * endpoints.initial;
        maximum = ((participants.maximum == max) || (endpoints.maximum == max))
                      ? max
                      : participants.maximum * endpoints.maximum;
        increment = (std::max)(participants.increment, endpoints.increment);

        return {initial, maximum, increment};
    }
};

const RTPSParticipantAllocationAttributes c_default_RTPSParticipantAllocationAttributes =
    RTPSParticipantAllocationAttributes();

}  // namespace xmlparser
}  // namespace vbsutil

#endif
